function MiscUtils() {
};

MiscUtils.conjunction = 1;
MiscUtils.disjunction = 2;

/**
 * Generate a random string
 */
MiscUtils.unique = function() {
  var unique = 'u' + parseInt(new Date().getTime() * Math.random());
  return unique;
};

/**
 * 
 */
MiscUtils.digits = function(value, size) {
  var prefix = '';
  for (var i = 0, il = size - value.toString().length; i < il; i++) {
    prefix += '0';
  }
  return prefix + value;
};

/**
 * Copy an object
 */
MiscUtils.clone = function(object) {
  return JSON.parse(JSON.stringify(object));
};

/**
 * Display content input from text area in div
 */
MiscUtils.dispTextArea = function(content) {
  span = document.createElement('span');
  var str = '';
  for (var i = 0, il = content.length; i < il; i++) {
    if (content.charAt(i) != '\n') {
      str += content.charAt(i);
    } else {
      span.appendChild(document.createTextNode(str));
      span.appendChild(document.createElement('br'));
      str = '';
    }
  }
  span.appendChild(document.createTextNode(str));
  return span
};

/**
 * Display a customised dialog
 */
MiscUtils.dialog = function(popupBox, pos, content, func1, func2, options) {
  var table, tr, td, btn;
  if (options && options.pop) {
    table = document.createElement('table');
    table.cellPadding = 0;
    table.cellSpacing = 0;
    popupBox._open(table, { pos: pos, t: (options && options.t) ? options.t : '', width: (options && options.width) ? options.width : null, height: (options && options.height) ? options.height : null, pop: (options && options.pop) ? options.pop : null });
    tr = table.insertRow(-1);
    td = tr.insertCell(-1);
    td.appendChild(content);
    tr = table.insertRow(-1);
    td = tr.insertCell(-1);
    td.style.textAlign = 'center';
    if (func1 || func2) {
      if (func1) {
        btn = DOMUtils.createInput(null, null, 'button', (options && options.ok) ? options.ok : 'OK', null);
        btn.className = 'button';
        btn.onclick = func1;
        td.appendChild(btn);
      }
      if (func2) {
        btn = DOMUtils.createInput(null, null, 'button', (options && options.cancel) ? options.cancel : 'Cancel', null);
        btn.className = 'button';
        btn.onclick = func2;
        td.appendChild(btn);
      }
    }
  } else {
    table = document.createElement('table');
    popupBox._open(table, { pos: pos, t: (options && options.t) ? options.t : '', width: (options && options.width) ? options.width : null, height: (options && options.height) ? options.height : null, pop: (options && options.pop) ? options.pop : null, func: (options && options.func) ? options.func : null });
    tr = table.insertRow(-1);
    td = tr.insertCell(-1);
    td.appendChild(content);
    tr = table.insertRow(-1);
    td = tr.insertCell(-1);
    td.style.padding = '10px 0 2px 0';
    td.style.textAlign = 'center';
    if (func1 || func2) {
      if (func1) {
        btn = DOMUtils.createInput(null, null, 'button', (options && options.ok) ? options.ok : 'OK', null);
        btn.className = 'button';
        btn.style.marginBottom = '13px';
        btn.onclick = func1;
        td.appendChild(btn);
      }
      if (func2) {
        btn = DOMUtils.createInput(null, null, 'button', (options && options.cancel) ? options.cancel : 'Cancel', null);
        btn.className = 'button';
        btn.style.marginBottom = '13px';
        btn.onclick = func2;
        td.appendChild(btn);
      }
    }
  }
};

/**
 * Display an alert dialog
 */
MiscUtils.alert = function(popupBox, pos, text) {
  var div = document.createElement('div');
  div.appendChild(document.createTextNode(text));
  div.style.margin = '0 0 10px 0';
  MiscUtils.dialog(popupBox, pos, div, function() { popupBox._close(); }, null);
};

/**
 * Display a loading dialog
 */
MiscUtils.load = function(popupBox, pos, text) {
  var div = document.createElement('div');
  var img = document.createElement('img');
  img.src = 'images/common/loading.gif';
  img.style.margin = '0 0 5px 0';
  div.appendChild(img);
  div.appendChild(document.createElement('br'));
  div.appendChild(document.createTextNode(text));
  div.style.margin = '0 0 5px 0';
  MiscUtils.dialog(popupBox, pos, div, null, null);
};

/**
 * Find elements from an array by specifed conditions and mode
 */
MiscUtils.find = function(array, conditions, mode) {
  mode = (mode) ? mode : MiscUtils.conjunction;
  if (mode == MiscUtils.conjunction) {
    return this.conjoin(array, conditions);
  } else if (mode == MiscUtils.disjunction) {
    return this.disjoin(array, conditions);
  } else {
    return [];
  }
};

/**
 * INTERNAL FUNCTION USED BY MiscUtils.find
 */
MiscUtils.conjoin = function(array, conditions) {
  var result = [];
  for (var i = 0, il = array.length; i < il; i++) {
    var tmp = array[i];
    var required = true;
    for (var j = 0, jl = conditions.length; j < jl; j++) {
      var condition = conditions[j];
      var value = tmp;
      for (var k = 0, kl = condition.attrs.length; k < kl; k++) {
        var attr = condition.attrs[k];
        value = value[attr];
      }
      if (condition.unequal) {
        if (value == condition.value) {
          required = false;
        }
      } else {
        if (value != condition.value) {
          required = false;
        }
      }
    }
    if (required) {
      result[result.length] = tmp;
    }
  }
  return result;
};

/**
 * INTERNAL FUNCTION USED BY MiscUtils.find
 */
MiscUtils.disjoin = function(array, conditions) {
  var result = [];
  for (var i = 0, il = array.length; i < il; i++) {
    var tmp = array[i];
    for (var j = 0, jl = conditions.length; j < jl; j++) {
      var condition = conditions[j];
      var value = tmp;
      for (var k = 0, kl = condition.attrs.length; k < kl; k++) {
        var attr = condition.attrs[k];
        value = value[attr];
      }
      if (condition.unequal) {
        if (value != condition.value) {
          result[result.length] = tmp;
        }
      } else {
        if (value == condition.value) {
          result[result.length] = tmp;
        }
      }
    }
  }
  return result;
};

/**
 * Remove element(s) from an array by a specified attribute
 */
MiscUtils.remove = function(array, elem, attr) {
  for (var i = 0, il = array.length; i < il; i++) {
    var tmp = array[i];
    if ((!attr && elem.id == tmp.id) || (attr && elem[attr] == tmp[attr])) {
      array.splice(i, 1);
      break;
    }
  }
  return array;
};

/**
 * Sort an array objects by specified attribute(s)
 */
MiscUtils.sort = function(array, attrs) {
  var func = function(a, b) { var v1 = a, v2 = b;
                              for (var i = 0, il = attrs.length; i < il; i++) {
                                v1 = v1[attrs[i]];
                                v2 = v2[attrs[i]]
                              }
                              if (isNaN(v1) || isNaN(v2)) {
                                if (v1 && v2 && v1.toString().valueOf() > v2.toString().valueOf()) {
                                  return true;
                                }
                              } else {
                                if (v1 && v2 && parseFloat(v1, 10) > parseFloat(v2, 10)) {
                                  return true;
                                }
                              }
                              return false;
                            };
  array.sort(func);
};

/**
 * Encrypt from string to characters
 */
MiscUtils.encrypt = function(str) {
  if ('{{$smarty.const.MODE|escape:'javascript'}}' == Constant.MODE_PUBLIC) {
    var result = '';
    for (i = 0, il = str.length; i < il; i++) {
      result += this.digits(str.charCodeAt(i).toString(16), 2);
    }
    return result;
  } else {
    return str;
  }
};

/**
 * Decrypt from characters to string
 */
MiscUtils.decrypt = function(str) {
  if ('{{$smarty.const.MODE|escape:'javascript'}}' == Constant.MODE_PUBLIC) {
    var result = '';
    for (i = 0, il = str.length; i < il; i += 2) {
      result += String.fromCharCode(parseInt(str.substring(i, i + 2), 16));
    }
    return result;
  } else {
    return str;
  }
};

/**
 * Return all the months
 */
MiscUtils.months = function() {
  return ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];
};

/**
 * Return years (now - 50 years ago)
 */
MiscUtils.years = function() {
  var now = new Date().getYear() + 1900;
  var years = [];
  for (var i = now, il = now - 50; i > il; i--) {
    years[years.length] = i;
  }
  return years;
};

/**
 * 
 */
MiscUtils.n2m = function(n_value) {
  //validate input
  if (isNaN(Number(n_value))) {
    return 'ERROR';
  }

  // save the sign
  var b_negative = Boolean(n_value < 0);
  n_value = Math.abs(n_value);

  // round to 1/100 precision, add ending zeroes if needed
  var s_result = String(Math.round(n_value * 1e2) % 1e2 + '00').substring(0, 2);

  // separate all orders
  var b_first = true;
  var s_subresult;
  while (n_value >= 1) {
    s_subresult = (n_value >= 1e3 ? '00' : '') + Math.floor(n_value % 1e3);
    s_result = s_subresult.slice(-3) + (b_first ? '.' : ',') + s_result;
    b_first = false;
    n_value = n_value / 1e3;
  }
  // add at least one integer digit
  if (b_first) {
    s_result = '0.' + s_result;
  }

  // apply formatting and return
  return b_negative ? '($' + s_result + ')' : '$' + s_result;
};

MiscUtils.m2n = function(m_value) {
  return Number(m_value.replace(/[^0-9\.\-]+/g,""));
}


MiscUtils.filename = function(str, len) {
  if (str.length < len) {
    return str;
  }
  
  var idx = str.lastIndexOf('.');
  var ext = str.substr(idx);
  
  if (ext.length > len) {
    return str.substr(0, len) + '...';
  } else {
    var remain = len - ext.length;
    if (remain % 2 != 0) {
      remain -= 1;
    }
    var left = str.substr(0, remain / 2);
    var right = str.substr(idx - remain / 2, remain / 2);
    return left + '...' + right + ext;
  }
};

MiscUtils.txt2span = function(content, rows) {
  var span = document.createElement('span');
  var str = '';
  for (var i = 0, il = content.length; i < il && rows > 0; i++) {
    if (content.charAt(i) != '\n') {
      str += content.charAt(i);
    } else {
      span.appendChild(document.createTextNode(str));
      span.appendChild(document.createElement('br'));
      str = '';
      rows--;
      if (rows <= 0 && i < il) {
        span.appendChild(document.createTextNode('...'));
      }
    }
  }
  span.appendChild(document.createTextNode(str));
  return span
};
